﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using PaintDotNet;
using PaintDotNet.Effects;
using PaintDotNet.PropertySystem;
using PaintDotNet.IndirectUI;
using LibFiltr;

namespace BilateralFilterPlugin
{
    public class PluginSupportInfo : IPluginSupportInfo
    {
        public string Author
        {
            get
            {
                return "UrFU Radiotechnical facultet";
            }
        }
        public string Copyright
        {
            get
            {
                return "Copyright © 2011";
            }
        }

        public string DisplayName
        {
            get
            {
                return "BilateralFilterPlugin";
            }
        }

        public Version Version
        {
            get
            {
                return base.GetType().Assembly.GetName().Version;
            }
        }

        public Uri WebsiteUri
        {
            get
            {
                return new Uri("http://paintnoisefilter.codeplex.com/");
            }
        }
    }


    [PluginSupportInfo(typeof(PluginSupportInfo), DisplayName = "BilateralFilter")]
    public class BilateralFilterPlugin : PropertyBasedEffect
    {
        private BilateralFilter _filter;
        private int Radius = 0;
        private double Sigma_d = .1;
        private double Sigma_r = .1;

        public static string StaticName
        {
            get
            {
                return "Bilateral filter";
            }
        }

        public static Image StaticIcon
        {
            get
            {
                return new Bitmap(typeof(BilateralFilterPlugin), "BilateralFilterPlugin.ico");
            }
        }

        public static string StaticSubMenuName
        {
            get
            {
                return "Filtr"; // Use for no submenu
                // return "My SubMenu"; // Use for custom submenu
            }
        }

        public BilateralFilterPlugin()
            : base(StaticName, StaticIcon, StaticSubMenuName, EffectFlags.Configurable)
        {
            this.Radius = 1;
            this.Sigma_d = .1;
            this.Sigma_r = .1;
        }

        public enum PropertyNames
        {
            Radius,
            Sigma_d,
            Sigma_r
        }

        protected override PropertyCollection OnCreatePropertyCollection()
        {
            List<Property> props = new List<Property>();

            props.Add(new Int32Property(PropertyNames.Radius, 1, 0, 10));
            props.Add(new DoubleProperty(PropertyNames.Sigma_d, .1, .1, 10.0));
            props.Add(new DoubleProperty(PropertyNames.Sigma_r, .1, .1, 255.0));

            return new PropertyCollection(props);
        }

        protected override ControlInfo OnCreateConfigUI(PropertyCollection props)
        {
            ControlInfo configUI = CreateDefaultConfigUI(props);

            configUI.SetPropertyControlValue(PropertyNames.Radius, ControlInfoPropertyNames.DisplayName, "Radius");
            configUI.SetPropertyControlValue(PropertyNames.Sigma_d, ControlInfoPropertyNames.DisplayName, "Domen deviation");
            configUI.SetPropertyControlValue(PropertyNames.Sigma_r, ControlInfoPropertyNames.DisplayName, "Intensity deviation");

            return configUI;
        }

        protected override void OnSetRenderInfo(PropertyBasedEffectConfigToken newToken, RenderArgs dstArgs, RenderArgs srcArgs)
        {
            this.Radius = newToken.GetProperty<Int32Property>(PropertyNames.Radius).Value;
            this.Sigma_d = newToken.GetProperty<DoubleProperty>(PropertyNames.Sigma_d).Value;
            this.Sigma_r = newToken.GetProperty<DoubleProperty>(PropertyNames.Sigma_r).Value;

            base.OnSetRenderInfo(newToken, dstArgs, srcArgs);
        }


        protected override void OnCustomizeConfigUIWindowProperties(PropertyCollection props)
        {
            // Change the effect's window title
            props[ControlInfoPropertyNames.WindowTitle].Value = "Bilateral filter";
            base.OnCustomizeConfigUIWindowProperties(props);
        }

        protected override unsafe void OnRender(Rectangle[] rois, int startIndex, int length)
        {
            if (length == 0) return;

            _filter = new BilateralFilter(Radius, Sigma_d, Sigma_r);

            for (int i = startIndex; i < startIndex + length; ++i)
            {
                Render(DstArgs.Surface, SrcArgs.Surface, rois[i]);
            }
        }

        void Render(Surface dst, Surface src, Rectangle rect)
        {
            Rectangle selection = this.EnvironmentParameters.GetSelection(src.Bounds).GetBoundsInt();
            _filter.Filter(dst, src, selection, rect);
        }
    }
}

